"use strict";

const DbMixin = require("../mixins/db.mixin");
const path = require('path');
const fs = require('fs').promises;
const sharp = require('sharp');

/**
 * @typedef {import('moleculer').ServiceSchema} ServiceSchema Moleculer's Service Schema
 * @typedef {import('moleculer').Context} Context Moleculer's Context
 */

/** @type {ServiceSchema} */
module.exports = {
    name: "images",

    /**
     * Mixins
     */
    mixins: [DbMixin("images")],

    /**
     * Settings
     */
    settings: {
        // Available fields in the responses
        fields: [
            "_id",
            "id",
            "name",
            "url",
            "size",
            "width",
            "height",
            "createdAt",
            "updatedAt"
        ],

        // Validator for the `create` & `insert` actions.
        entityValidator: {
            name: "string",
            url: "string",
            size: "number",
            width: "number|optional",
            height: "number|optional"
        },

        // 配置文件上传目录（相对于项目根目录）
        // 可以通过环境变量 IMAGE_UPLOAD_DIR 覆盖
        uploadDir: process.env.IMAGE_UPLOAD_DIR || "uploads/images",

        // 是否使用日期目录结构 (如: uploads/images/2024/01/15/)
        useDateFolder: true
    },

    /**
     * Dependencies
     */
    dependencies: [],

    /**
     * Actions
     */
    actions: {
        // --- IMAGE MANAGEMENT ACTIONS ---

        /**
         * Get images list
         */
        getImages: {
            rest: "GET /images",
            cache: false,
            async handler(ctx) {
                const { keyword, page = 1, pageSize = 20 } = ctx.params;

                try {
                    // Build query object
                    const query = {};
                    if (keyword) {
                        query.name = { $regex: keyword, $options: "i" };
                    }

                    // Calculate pagination
                    const skip = (parseInt(page) - 1) * parseInt(pageSize);
                    const limit = parseInt(pageSize);

                    // Get images from the database with pagination
                    const [images, total] = await Promise.all([
                        this.adapter.find(query, {
                            skip: skip,
                            limit: limit,
                            sort: { createdAt: -1 }
                        }),
                        this.adapter.count(query)
                    ]);

                    // Format the response data
                    const formattedImages = images.map(image => {
                        // 生成完整URL（兼容新旧数据）
                        let fullUrl = image.url;
                        if (image.path && !image.url.startsWith('http')) {
                            // 使用相对路径生成完整URL
                            if (ctx.meta.$requestHeaders && ctx.meta.$requestHeaders.host) {
                                const host = ctx.meta.$requestHeaders.host;
                                const protocol = ctx.meta.$requestHeaders['x-forwarded-proto'] || 'http';
                                fullUrl = `${protocol}://${host}/${image.path}`;
                            } else {
                                fullUrl = `http://localhost:3000/${image.path}`;
                            }
                        }

                        return {
                            id: image._id.toString(),
                            name: image.name,
                            url: fullUrl,
                            path: image.path || image.url,
                            size: image.size,
                            mimeType: image.mimeType,
                            width: image.width || 0,
                            height: image.height || 0,
                            createdAt: image.createdAt ? image.createdAt.toLocaleString('zh-CN') : new Date().toLocaleString('zh-CN'),
                            updatedAt: image.updatedAt ? image.updatedAt.toLocaleString('zh-CN') : new Date().toLocaleString('zh-CN')
                        };
                    });

                    return {
                        code: 200,
                        data: {
                            list: formattedImages,
                            total: total,
                            page: parseInt(page),
                            pageSize: parseInt(pageSize)
                        },
                        message: "success"
                    };
                } catch (error) {
                    this.logger.error(`操作失败: ${error.message}`, error);
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },

        /**
         * Get image detail
         */
        getImageDetail: {
            rest: "GET /images/:id",
            cache: false,
            params: {
                id: "string"
            },
            async handler(ctx) {
                const { id } = ctx.params;

                try {
                    // Find the image in the database
                    const image = await this.adapter.findById(id);
                    if (!image) {
                        return {
                            code: 404,
                            data: null,
                            message: "图片不存在"
                        };
                    }

                    // Format the response data
                    // 生成完整URL（兼容新旧数据）
                    let fullUrl = image.url;
                    if (image.path && !image.url.startsWith('http')) {
                        // 使用相对路径生成完整URL
                        if (ctx.meta.$requestHeaders && ctx.meta.$requestHeaders.host) {
                            const host = ctx.meta.$requestHeaders.host;
                            const protocol = ctx.meta.$requestHeaders['x-forwarded-proto'] || 'http';
                            fullUrl = `${protocol}://${host}/${image.path}`;
                        } else {
                            fullUrl = `http://localhost:3000/${image.path}`;
                        }
                    }

                    const formattedImage = {
                        id: image._id.toString(),
                        name: image.name,
                        url: fullUrl,
                        path: image.path || image.url,
                        size: image.size,
                        mimeType: image.mimeType,
                        width: image.width || 0,
                        height: image.height || 0,
                        createdAt: image.createdAt ? image.createdAt.toLocaleString('zh-CN') : new Date().toLocaleString('zh-CN'),
                        updatedAt: image.updatedAt ? image.updatedAt.toLocaleString('zh-CN') : new Date().toLocaleString('zh-CN')
                    };

                    return {
                        code: 200,
                        data: formattedImage,
                        message: "success"
                    };
                } catch (error) {
                    if (error.message === "图片不存在") {
                        return {
                            code: 404,
                            data: null,
                            message: "图片不存在"
                        };
                    }

                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },

        /**
         * Upload image
         */
        uploadImage: {
            rest: "POST /images/upload",
            cache: false,
            params: {
                name: { type: "string", optional: true },
                $file: { type: "object", optional: true }
            },
            async handler(ctx) {
                try {
                    // 从多个可能的位置获取文件信息
                    const file = ctx.params.$file || ctx.meta.$multipart || ctx.meta.req?.file || ctx.meta.file;

                    if (!file) {
                        return {
                            code: 400,
                            data: null,
                            message: "请上传图片文件"
                        };
                    }

                    // 检查文件类型
                    const allowedTypes = [
                        'image/jpeg',
                        'image/jpg',
                        'image/png',
                        'image/gif',
                        'image/webp',
                        'image/svg+xml'
                    ];
                    if (!allowedTypes.includes(file.mimetype)) {
                        return {
                            code: 400,
                            data: null,
                            message: "不支持的文件类型，仅支持jpg、png、gif、webp格式"
                        };
                    }

                    // 检查文件大小 (最大10MB)
                    const maxSize = 10 * 1024 * 1024; // 10MB
                    if (file.size > maxSize) {
                        return {
                            code: 400,
                            data: null,
                            message: "文件大小超过限制，最大支持10MB"
                        };
                    }

                    // 获取自定义名称参数（不允许客户端指定路径）
                    const { name: customName } = ctx.params;

                    // 打印调试信息
                    this.logger.info("文件上传参数:", {
                        fileName: file.filename,
                        originalName: file.originalname,
                        size: file.size,
                        mimetype: file.mimetype,
                        customName: customName
                    });

                    // 获取图片尺寸
                    let width = 0;
                    let height = 0;

                    // 使用sharp获取图片尺寸
                    try {
                        // 如果文件有buffer，直接使用；否则从磁盘读取
                        let imageBuffer;
                        if (file.buffer) {
                            imageBuffer = file.buffer;
                        } else if (file.path) {
                            // 如果Multer保存了临时文件路径
                            imageBuffer = await fs.readFile(file.path);
                        } else {
                            // 尝试从public目录读取已上传的文件
                            const uploadedFilePath = path.join(process.cwd(), 'public', relativePath);
                            if (await fs.access(uploadedFilePath).then(() => true).catch(() => false)) {
                                imageBuffer = await fs.readFile(uploadedFilePath);
                            }
                        }

                        if (imageBuffer) {
                            const metadata = await sharp(imageBuffer).metadata();
                            width = metadata.width || 0;
                            height = metadata.height || 0;
                            this.logger.info(`图片尺寸: ${width}x${height}`);
                        }
                    } catch (dimError) {
                        this.logger.warn('获取图片尺寸失败:', dimError.message);
                        // 如果获取失败，继续使用默认值0
                    }

                    // 构建文件路径（使用配置的安全路径）
                    let relativePath;
                    if (this.settings.useDateFolder) {
                        // 使用日期目录结构
                        const now = new Date();
                        const year = now.getFullYear();
                        const month = String(now.getMonth() + 1).padStart(2, '0');
                        const day = String(now.getDate()).padStart(2, '0');
                        relativePath = path.join(
                            this.settings.uploadDir,
                            year.toString(),
                            month,
                            day,
                            file.filename
                        ).replace(/\\/g, '/');
                    } else {
                        // 使用固定目录
                        relativePath = path.join(this.settings.uploadDir, file.filename).replace(/\\/g, '/');
                    }

                    // 构建图片数据对象
                    const uploadedImageData = {
                        name: customName || file.filename,
                        originalName: file.originalname,
                        url: `/${relativePath}`,
                        path: relativePath,
                        size: file.size,
                        mimeType: file.mimetype,
                        width: width,
                        height: height,
                        createdAt: new Date(),
                        updatedAt: new Date()
                    };

                    // 保存图片信息到数据库
                    const newImage = await this.adapter.insert(uploadedImageData);

                    // 生成可访问的完整URL
                    let fullUrl;
                    if (ctx.meta.req && ctx.meta.req.protocol && ctx.meta.req.get) {
                        const baseUrl = `${ctx.meta.req.protocol}://${ctx.meta.req.get('host')}`;
                        fullUrl = baseUrl + newImage.url;
                    } else if (ctx.meta.$requestHeaders) {
                        // 从请求头中获取host
                        const host = ctx.meta.$requestHeaders.host || 'localhost:3000';
                        const protocol = ctx.meta.$requestHeaders['x-forwarded-proto'] || 'http';
                        fullUrl = `${protocol}://${host}${newImage.url}`;
                    } else {
                        // 默认URL
                        fullUrl = `http://localhost:3000${newImage.url}`;
                    }

                    // Format the response data
                    const formattedImage = {
                        id: newImage._id.toString(),
                        name: newImage.name,
                        originalName: newImage.originalName,
                        url: fullUrl,
                        path: newImage.path,
                        size: newImage.size,
                        mimeType: newImage.mimeType,
                        width: newImage.width || 0,
                        height: newImage.height || 0,
                        createdAt: newImage.createdAt.toLocaleString('zh-CN'),
                        updatedAt: newImage.updatedAt.toLocaleString('zh-CN')
                    };

                    return {
                        code: 200,
                        data: formattedImage,
                        message: "上传成功"
                    };
                } catch (error) {
                    return {
                        code: 500,
                        data: null,
                        message: "上传失败"
                    };
                }
            }
        },

        /**
         * Update image info
         */
        updateImage: {
            rest: "PUT /images/:id",
            cache: false,
            params: {
                id: "string",
                name: "string"
            },
            async handler(ctx) {
                const { id, name } = ctx.params;

                try {
                    // Find the image in the database
                    const image = await this.adapter.findById(id);
                    if (!image) {
                        return {
                            code: 404,
                            data: null,
                            message: "图片不存在"
                        };
                    }

                    // Update the image in the database
                    const updatedImage = await this.adapter.updateById(id, {
                        $set: {
                            name: name,
                            updatedAt: new Date()
                        }
                    });

                    // Format the response data
                    const formattedImage = {
                        id: updatedImage._id.toString(),
                        name: updatedImage.name,
                        url: updatedImage.url,
                        size: updatedImage.size,
                        width: updatedImage.width || 0,
                        height: updatedImage.height || 0,
                        createdAt: updatedImage.createdAt ? updatedImage.createdAt.toLocaleString('zh-CN') : new Date().toLocaleString('zh-CN'),
                        updatedAt: new Date().toLocaleString('zh-CN')
                    };

                    return {
                        code: 200,
                        data: formattedImage,
                        message: "更新成功"
                    };
                } catch (error) {
                    if (error.message === "图片不存在") {
                        return {
                            code: 404,
                            data: null,
                            message: "图片不存在"
                        };
                    }

                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },

        /**
         * Delete image
         */
        deleteImage: {
            rest: "DELETE /images/:id",
            cache: false,
            params: {
                id: "string"
            },
            async handler(ctx) {
                const { id } = ctx.params;

                try {
                    // Find the image in the database
                    const image = await this.adapter.findById(id);
                    if (!image) {
                        return {
                            code: 404,
                            data: null,
                            message: "图片不存在"
                        };
                    }

                    // Delete the physical file if it exists
                    if (image.path) {
                        const filePath = path.join(process.cwd(), 'public', image.path);
                        try {
                            await fs.unlink(filePath);
                            this.logger.info(`删除文件成功: ${filePath}`);
                        } catch (fileError) {
                            // 文件可能已经不存在，记录警告但继续删除数据库记录
                            this.logger.warn(`删除文件失败: ${filePath}`, fileError.message);
                        }
                    }

                    // Delete the image from the database
                    await this.adapter.removeById(id);

                    return {
                        code: 200,
                        data: null,
                        message: "删除成功"
                    };
                } catch (error) {
                    if (error.message === "图片不存在") {
                        return {
                            code: 404,
                            data: null,
                            message: "图片不存在"
                        };
                    }

                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },

        /**
         * Batch delete images
         */
        batchDeleteImages: {
            rest: "DELETE /images/batch",
            cache: false,
            params: {
                ids: "array"
            },
            async handler(ctx) {
                const { ids } = ctx.params;
                let objectIds = ids.map(id => this.adapter.stringToObjectID(id));
                try {
                    // Find all images with the given IDs
                    const images = await this.adapter.find({
                        query: {
                            _id: { $in: objectIds }
                        }
                    });

                    // Check for invalid IDs
                    const validIds = images.map(image => image._id.toString());
                    const invalidIds = ids.filter(id => !validIds.includes(id));

                    if (invalidIds.length > 0) {
                        return {
                            code: 404,
                            data: null,
                            message: `图片ID ${invalidIds.join(', ')} 不存在`
                        };
                    }

                    // Delete the physical files
                    const deletePromises = images.map(async (image) => {
                        if (image.path) {
                            const filePath = path.join(__dirname, '..',image.path);
                            try {
                                await fs.unlink(filePath);
                                this.logger.info(`删除文件成功: ${filePath}`);
                            } catch (fileError) {
                                // 文件可能已经不存在，记录警告但继续
                                this.logger.warn(`删除文件失败: ${filePath}`, fileError.message);
                            }
                        }
                    });

                    // 等待所有文件删除操作完成
                    await Promise.all(deletePromises);

                    // Delete the images from the database
                    await this.adapter.removeMany({
                        _id: { $in: objectIds }
                    });

                    return {
                        code: 200,
                        data: null,
                        message: "删除成功"
                    };
                } catch (error) {
                    if (error.message.includes("不存在")) {
                        return {
                            code: 404,
                            data: null,
                            message: error.message
                        };
                    }

                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },

        /**
         * Get file upload config
         */
        getFileUploadConfig: {
            rest: "GET /files/config",
            cache: false,
            async handler(ctx) {
                try {
                    // In a real implementation, you would get this from a configuration service or database
                    // For now, we'll return a static config which could be stored in a database in a real app

                    // This would typically come from a configuration collection or environment variables
                    const uploadConfig = {
                        maxSize: 10485760, // 10MB
                        allowedTypes: [
                            "image/jpeg",
                            "image/png",
                            "image/gif",
                            "image/webp"
                        ],
                        maxWidth: 4096,
                        maxHeight: 4096,
                        quality: 0.92
                    };

                    return {
                        code: 200,
                        data: uploadConfig,
                        message: "success"
                    };
                } catch (error) {
                    this.logger.error(`操作失败: ${error.message}`, error);
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        },

        /**
         * Update dimensions for existing images
         * This is useful for updating images that were uploaded before dimension extraction was implemented
         */
        updateImageDimensions: {
            rest: "POST /images/update-dimensions",
            cache: false,
            async handler(ctx) {
                try {
                    // Get all images without dimensions
                    const images = await this.adapter.find({
                        query: {
                            $or: [
                                { width: { $exists: false } },
                                { height: { $exists: false } },
                                { width: 0 },
                                { height: 0 }
                            ]
                        }
                    });

                    this.logger.info(`Found ${images.length} images without dimensions`);

                    let updated = 0;
                    let failed = 0;

                    for (const image of images) {
                        try {
                            // Build the file path
                            const filePath = path.join(process.cwd(), 'public', image.path || image.url);

                            // Check if file exists
                            const fileExists = await fs.access(filePath).then(() => true).catch(() => false);
                            if (!fileExists) {
                                this.logger.warn(`File not found: ${filePath}`);
                                failed++;
                                continue;
                            }

                            // Read the file and get dimensions
                            const imageBuffer = await fs.readFile(filePath);
                            const metadata = await sharp(imageBuffer).metadata();

                            if (metadata.width && metadata.height) {
                                // Update the image with dimensions
                                await this.adapter.updateById(image._id, {
                                    $set: {
                                        width: metadata.width,
                                        height: metadata.height,
                                        updatedAt: new Date()
                                    }
                                });
                                updated++;
                                this.logger.info(`Updated dimensions for image ${image.name}: ${metadata.width}x${metadata.height}`);
                            }
                        } catch (err) {
                            this.logger.error(`Failed to update dimensions for image ${image.name}:`, err.message);
                            failed++;
                        }
                    }

                    return {
                        code: 200,
                        data: {
                            total: images.length,
                            updated: updated,
                            failed: failed
                        },
                        message: `成功更新 ${updated} 张图片尺寸，失败 ${failed} 张`
                    };
                } catch (error) {
                    this.logger.error(`批量更新图片尺寸失败: ${error.message}`, error);
                    return {
                        code: 500,
                        data: null,
                        message: "服务器内部错误"
                    };
                }
            }
        }
    },

    /**
     * Methods
     */
    methods: {},

    /**
     * Events
     */
    events: {},

    /**
     * Service created lifecycle event handler
     */
    created() { },

    /**
     * Service started lifecycle event handler
     */
    async started() {
        // Seed some mock data if needed
    },

    /**
     * Service stopped lifecycle event handler
     */
    async stopped() { }
};